package org.guegan.util.dircompare.main;

import java.io.File;
import java.io.FileFilter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.guegan.util.dircompare.bean.DirBean;
import org.guegan.util.dircompare.bean.FileBean;
import org.guegan.util.dircompare.util.DirUtil;
import org.guegan.util.dircompare.util.FileToSignature;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;

public class DirScanner extends MainModule {
	private FileToSignature signer;
	private FileFilter filter;
	private static Log log = LogFactory.getLog(DirScanner.class);
	private File root;
	
	public DirScanner() {
	}

	@Override
	protected void doExecute() throws Exception {
		scanDir(root);
	}
	
	public void scanDir(File dir) {
		File[] contents = dir.listFiles(filter);
		log.info(">>> " + dir + ": " + (contents != null ? contents.length : 0) + " elements(s)");
		StringBuilder signatures = new StringBuilder(4096);
		DirBean parent = DirUtil.getInstance().getDir(dir, getSession());
		int nbFiles = 0;
		if (contents != null) {
			for (File file : contents) {
				if (file.isDirectory()) {
					scanDir(file);
				}
				else {
					log.debug("Examining " + file);
					nbFiles++;
					Criteria crit = getSession().createCriteria(FileBean.class);
					crit.add(Restrictions.eq("name", file.getName()));
					crit.add(Restrictions.eq("parent", parent));
					FileBean existing = (FileBean) crit.uniqueResult();
					if (existing != null) {
						if (existing.getTime().getTime() != file.lastModified()) {
							String signature = signer.calculate(file);
							if (!existing.getSignature().equals(signature)) {
								log.warn("Changing signature for file " + file.getPath());
								existing.setSignature(signature);
							}
						}
						existing.setPresent(true);
						getSession().save(existing);
					}
					else {
						String signature = signer.calculate(file);
						existing = new FileBean();
						existing.setParent(parent);
						existing.setSignature(signature);
						existing.setFile(file);
						getSession().save(existing);
					}
					signatures.append(existing.getSignature());
				}
				parent.setSignature(signer.calculate(signatures.toString()));
				parent.setNbFiles(nbFiles);
				parent.setPresent(true);
				getSession().save(parent);
			}
		}
		log.info("<<< " + dir);
	}
	
	public FileToSignature getSigner() {
		return signer;
	}

	public void setSigner(FileToSignature signer) {
		this.signer = signer;
	}

	public FileFilter getFilter() {
		return filter;
	}

	public void setFilter(FileFilter filter) {
		this.filter = filter;
	}

	public void setRoot(File root) {
		this.root = root;
	}

	public File getRoot() {
		return root;
	}
	
}
